var ListBox = function() {
    /**
     *@private
     */
    this.component = $(document.createElement("select"));
    this.component.attr("multiple","multiple");
    this.component[0].owner = this;
    this.component.dblclick(function(event){
        this.owner.fire(ListBoxEvent.DOUBLE_CLICK, event);
    });
    this.component.change(function(event){
        this.owner.fire(ListBoxEvent.CHANGE, event);
    });
    /**
     *@private
     */
    this.element = {};
    /**
     *@private
     */
    this.nextSibling = null;
    /***
    * @private
    */
    this.labelFunction = function(item) {
        return item[this.dataField];
    }
    /***
     * Determina a função que será chamada ao gerar cada item da ListBox
     * @param func
     */
    this.setLabelfunction = function(func) {
        this.labelFunction = (func instanceof Function)  ? func : eval(func);
        this.makeComponentData();
    }
    /**
     *@private
     */
    this.events = {};
    /**
     * Data Provider do Componente
     * @type Collection
     */
    this.dataProvider = new Collection();
    /**
     *@private
     */
    this.container = {};
     /**
     *@private
     */
    this.dataField = "label";
    /**
     *@private
     */
    this.width = 300;
    /**
     *@private
     */
    this.height = 100;
    /**
     *@private
     */
    this.id = "listBox";

    /**
     * @private
     */
    this.setElement = function(element) {
        this.element = element;
        this.nextSibling = element.next();
        this.setContainer(element.parent());
        this.element.remove();
    }
    /**
     * @private
     */
    this.setDatafield = function(value) {
        this.dataField = value;
        this.makeComponentData();
    }
    /**
     * @private
     */
    this.setWidth = function(value) {
        this.width = value;
        this.component.css("width",parseInt(value));
        
    }
    /**
     * @private
     */
    this.setHeight = function(value) {
        this.height = value;
        this.component.css("height",parseInt(value));
    }
    /**
     * @private
     */
    this.setId = function(value) {
        this.id = value;
        this.component.attr("id",value);
        window[value] = this;
    }

    /**
     * Atribue o elemento onde ficará a <code>ListBox</code>
     * @param htmlElement
     * @example
     * myListBox.setContainer($("#parentElement"));
     */
    this.setContainer = function(htmlElement) {
        this.container = htmlElement;

        if (this.nextSibling.length > 0) {
            this.component.insertBefore(this.nextSibling);
        } else {
            this.container.append(this.component);
        }        
    }
    /**
     * Retorna o container onde está a <code>ListBox</code>
     * @return this.container
     */
    this.getContainer = function() {
        return this.container;
    }

    /**
     * Determina a <code>Collection</code> que será o data provider da <code>ListBox</code>
     * @param dataProvider Collection
     * @example
     * myListBox.setDataProvider(new Collection());
     */
    this.setDataProvider = function (dataProvider)  {
        this.dataProvider = dataProvider;
        this.dataProvider.owner = this;
        this.dataProvider.bind(CollectionEvent.DATA_CHANGED, function(event, eventData){event.target.owner.dataProviderChangedHandler(event, eventData);});
        this.makeComponentData();
    }

    /**
     * Handler do evento do <code>dataProvider</code>. Atualiza a ListBox
     * @param event
     * @param eventData
     * @private
     */
    this.dataProviderChangedHandler = function(event, eventData) {
        this.makeComponentData();
    }

    /**
     * Pega os dados do <code>dataProvider</code> e mostra no Componente
     */
    this.makeComponentData = function() {
        this.component.html("");
        for(var i = 0; i < this.dataProvider.size(); i++) {
            var option = $(document.createElement("option"));
                option.html(this.labelFunction(this.dataProvider.getItemAt(i)));
            this.component.append(option);
        }
    }

    /**
     * Retorna o item do <code>dataProvider</code> de acordo com o index selecionado na <code>ListBox</code>
     */
    this.selectedItem = function () {
        return this.dataProvider.getItemAt(this.component[0].selectedIndex);
    }
    /**
     * Retorna o index selecionado na <code>ListBox</code>
     */
    this.selectedIndex = function() {
        return this.component[0].selectedIndex;
    }

    /***
     * Adiciona um evento à instancia do objeto
     * @param eventName
     * @param callBack
     * @type ListBox
     * @example
     * function changeHandler(event) {
     *      alert("Data Changed!");
     * }
     * var myList = new ListBox();
     *     myList.bind(ListBoxEvent.CHANGE, changeHandler);
     */
    this.bind = function(eventName, callBack) {
        if (!this.events[eventName])
        this.events[eventName] = new Array();
        this.events[eventName].push(callBack)
        return this;
    }

    /***
     * Dispara o evento indicado
     * @param eventName
     * @param eventData
     * @return ArrayCollection
     */
    this.fire = function(eventName, eventData) {
        if (this.events[eventName]) {
            for(var i = 0; i < this.events[eventName].length; i++) {
                this.events[eventName][i]({target:this, data : eventData});
            }
        }
        return this;
    }

}

var ListBoxEvent = {
    /**
     * Evento Disparado ao alterar os selecionar um valor na <code>ListBox</code>
     * @example
     * function changeHandler(event) {
     *      alert("Data Changed!");
     * }
     * var myList = new ListBox();
     *     myList.bind(ListBoxEvent.CHANGE, changeHandler);
     * @eventType ListBoxEvent.CHANGE
     */
    CHANGE : "change=",
    /**
     * Evento disparado ao clicar duas vezes numa <code>ListBox</code>
     * @example
     * function doubleClickHandler(event) {
     *      alert("event");
     * }
     * var myList = new ListBox();
     *     myList.bind(ListBoxEvent.DOUBLE_CLICK, doubleClickHandler);
     * @eventType ListBoxEvent.DOUBLE_CLICK
     */
    DOUBLE_CLICK : "doubleClick="
}